package com.zytlifeservice.service.pay;

import com.qianmi.open.api.ApiException;
import com.qianmi.open.api.domain.elife.AdminItem;
import com.qianmi.open.api.request.CatvCreateBillRequest;
import com.qianmi.open.api.request.CatvItemsListRequest;
import com.qianmi.open.api.response.CatvCreateBillResponse;
import com.qianmi.open.api.response.CatvItemsListResponse;
import com.zytlifeservice.domain.Result;
import com.zytlifeservice.domain.User;
import com.zytlifeservice.domain.pay.AlipayOrder;
import com.zytlifeservice.domain.pay.BaseQmOrder;
import com.zytlifeservice.domain.pay.WiredTvRechargeOrder;
import com.zytlifeservice.domain.pay.WxPayOrder;
import com.zytlifeservice.exception.UserException;
import com.zytlifeservice.repository.UserRepository;
import com.zytlifeservice.repository.pay.AlipayOrderRepository;
import com.zytlifeservice.repository.pay.WiredTvRechargeOrderRepository;
import com.zytlifeservice.repository.pay.WxPayOrderRepository;
import com.zytlifeservice.util.Items;
import com.zytlifeservice.util.ResultUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 有线电视业务类
 * Created by Administrator on 2017/6/3.
 */
@Service
public class WiredTvRechargeOrderService {
    private static final Logger logger = LoggerFactory.getLogger(WiredTvRechargeOrderService.class);

    @Autowired
    private WiredTvRechargeOrderRepository wiredTvRechargeOrderRepository;//有线电视持久类

    @Autowired
    AlipayOrderRepository alipayOrderRepository;

    @Autowired
    WxPayService wxPayService;

    @Autowired
    WxPayOrderRepository wxPayOrderRepository;

    @Autowired
    AlipayService alipayService;

    @Autowired
    UserRepository userRepository;

    @Autowired
    PublicService publicService;


    //查询有线电视列表
    public Result sendTv(String city) throws Exception {
        System.out.println("进入有线电视商品列表查询方法");
        CatvItemsListRequest req = new CatvItemsListRequest();
        req.setItemName(city);
        CatvItemsListResponse response = publicService.execute(req);
        List<AdminItem> itemsList = response.getItems();
        List<Items> itemList = new ArrayList<Items>();//解析数据源
        if (null != itemsList && itemsList.size() > 0) {
            List<AdminItem> items = response.getItems();
            if (items == null || items.size() == 0) {
                //这里没有请求到数据。提示该地区尚未开通此服务
                return null;
            }
            List<Map<String, Object>> mapList = new ArrayList<>();
            for (AdminItem item : items) {
                String itemId = item.getItemId();
                String itemName = item.getItemName();
                String[] params = itemName.replaceAll("\\s{1,}", " ").split(" ");

                String type = params[params.length - 2];

                String name = params[1];
                String costStr = params[params.length - 1];
                costStr = costStr.replace("元", "").replace("直充", "").replace("慢充", "");
                String cost = costStr;
                Map<String, Object> contain = contain(mapList, name);
                if (contain != null) {
                    List<Item> list = (List<Item>) contain.get("itemArr");
                    if (costStr.contains("任意充") && isHold(list) || isRepeat(cost, list)) {  //多个任意充只处理一个。
                        continue;
                    }
                    list.add(new Item(itemId, cost));
                } else {
                    Map<String, Object> curBean = new HashMap<>();
                    curBean.put("itemName", name);
                    List<Item> list = new ArrayList<>();
                    list.add(new Item(itemId, cost));
                    curBean.put("itemArr", list);
                    mapList.add(curBean);
                }
            }
            return ResultUtil.success(mapList, "查询成功");
        } else {
            return ResultUtil.error(303, "该城市暂时未开通服务");
        }
    }

    private boolean isRepeat(String cost, List<Item> list) {
        for (Item item : list) {
            if (cost.equals(item.getMoney())) {
                return true;
            }
        }
        return false;
    }

    private boolean isHold(List<Item> list) {
        boolean isHold = false;
        for (Item bean : list) {
            if (bean.getMoney().contains("任意充")) {
                isHold = true;
                break;
            }
        }
        return isHold;
    }

    private Map<String, Object> contain(List<Map<String, Object>> mapList, String name) {
        for (Map<String, Object> map : mapList) {
            if (map.containsValue(name)) {
                return map;
            }
        }
        return null;
    }

    public String[] createOrder(String address, String rechargeAmount, String itemName, String itemId, String rechargeAccount, Long userId) throws ApiException {
        User one = userRepository.findOne(userId);
        if (one == null) {
            throw new UserException("用户不存在", 104);
        }
        String[] res = new String[2];
        AlipayOrder alipayOrder = new AlipayOrder();
        alipayOrder.setStoreId(one.getStoreId());
        alipayOrder.setSubject(itemName);//对应的后台的信息
        String outTradeNo = "zyt" + userId + System.currentTimeMillis()   //添加userId
                + (long) (Math.random() * 10000000L);
        alipayOrder.setOutTradeNo(outTradeNo);
        alipayOrder.setTotalAmount(rechargeAmount);
        alipayOrder.setUserId(userId);
        alipayOrder.setType(AlipayOrder.TYPE_CATV);
        alipayOrderRepository.save(alipayOrder);

        //同时，这里要生成千米的订单
        WiredTvRechargeOrder wiredTvRechargeOrder = new WiredTvRechargeOrder();
        wiredTvRechargeOrder.setRechargeAccount(rechargeAccount);
        wiredTvRechargeOrder.setAddress(address);
        wiredTvRechargeOrder.setItemId(itemId);
        wiredTvRechargeOrder.setOutTradeNo(outTradeNo);
        wiredTvRechargeOrder.setItemName(itemName);
        wiredTvRechargeOrder.setPayType(BaseQmOrder.PAY_TYPE_ALIPAY);
        wiredTvRechargeOrder.setUserId(userId);
        wiredTvRechargeOrder.setSaleAmount(rechargeAmount);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        wiredTvRechargeOrder.setOrderTime(sdf.format(new Date()));
        wiredTvRechargeOrder.setPayState("0");  //这里修改其状态。
        wiredTvRechargeOrder.setPayResult(BaseQmOrder.STATUS_INIT);
        if (!publicService.querySum(rechargeAmount)) {
            wiredTvRechargeOrder.setFailReason("直销商余额不足,取消支付宝预下单");
            wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);
            res[0] = "fail";
            res[1] = "直销商余额不足,取消支付宝预下单";
            return res;
        }
        publicService.setBaseOrderType(wiredTvRechargeOrder);
        wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);
        res[0] = "success";
        res[1] = alipayService.pay(alipayOrder) + "," + outTradeNo;
//        publicService.addScore(wiredTvRechargeOrder);
        return res;
    }

    public String[] wxCreateOrder(String address, String rechargeAmount, String itemName, String itemId, String rechargeAccount, Long userId, String ip) {
        User one = userRepository.findOne(userId);
        if (one == null) {
            throw new UserException("用户不存在", 104);
        }
        String[] res = new String[2];
        String outTradeNo = "zyt" + userId + System.currentTimeMillis()   //添加userId
                + (long) (Math.random() * 10000000L);
        WxPayOrder wxPayOrder = publicService.generateWxpayOrder(one, itemName, ip, rechargeAmount, outTradeNo,
                WxPayOrder.TYPE_CATV);
        wxPayOrderRepository.save(wxPayOrder);

        WiredTvRechargeOrder wiredTvRechargeOrder = new WiredTvRechargeOrder();
        wiredTvRechargeOrder.setRechargeAccount(rechargeAccount);
        wiredTvRechargeOrder.setAddress(address);
        wiredTvRechargeOrder.setItemId(itemId);
        wiredTvRechargeOrder.setOutTradeNo(outTradeNo);
        wiredTvRechargeOrder.setItemName(itemName);
        wiredTvRechargeOrder.setPayType(BaseQmOrder.PAY_TYPE_WXPAY);
        wiredTvRechargeOrder.setUserId(userId);
        wiredTvRechargeOrder.setSaleAmount(rechargeAmount);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        wiredTvRechargeOrder.setOrderTime(sdf.format(new Date()));
        wiredTvRechargeOrder.setPayState("0");  //这里修改其状态。
        wiredTvRechargeOrder.setPayResult(BaseQmOrder.STATUS_INIT);
        if (!publicService.querySum(rechargeAmount)) {
            wiredTvRechargeOrder.setFailReason("直销商余额不足,取消支付宝预下单");
            wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);
            res[0] = "fail";
            res[1] = "直销商余额不足,取消支付宝预下单";
            return res;
        }
        publicService.setBaseOrderType(wiredTvRechargeOrder);
        wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);
        res[0] = "success";
        res[1] = wxPayService.pay(wxPayOrder) + "," + outTradeNo;
        return res;
    }


    //这里要得到千米的订单信息。执行消费。
    public String payWiredTvChargeOrder(String outTradeNo) {
        WiredTvRechargeOrder wiredTvRechargeOrder = wiredTvRechargeOrderRepository.findByOutTradeNo(outTradeNo);
        logger.error("查询的order:{}", wiredTvRechargeOrder);
        CatvCreateBillRequest req = new CatvCreateBillRequest();
        req.setItemId(wiredTvRechargeOrder.getItemId());
        req.setRechargeAmount(wiredTvRechargeOrder.getSaleAmount());
        req.setRechargeAccount(wiredTvRechargeOrder.getRechargeAccount());
        req.setCallback(publicService.getBmCallbackUrl());
        req.setOuterTid(wiredTvRechargeOrder.getOutTradeNo());
        try {
            CatvCreateBillResponse response = publicService.execute(req);
            logger.error("支付状态:{}", response.isSuccess());
            logger.error("支付结果body:{}", response.getBody());
            if (!response.isSuccess()) {
                //处理错误
                //记录错误原因，同时，执行退款流程。
                wiredTvRechargeOrder.setFailReason(response.getSubMsg());
                wiredTvRechargeOrder.setPayResult(BaseQmOrder.STATUS_FAIL);
                wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);

                if (wiredTvRechargeOrder.getPayType() == BaseQmOrder.PAY_TYPE_ALIPAY) {
                    AlipayOrder byOutTradeNo = alipayOrderRepository.findByOutTradeNo(outTradeNo);
                    byOutTradeNo.setRefundReason(response.getSubMsg());
                    return alipayService.reFund(byOutTradeNo);
                } else if (wiredTvRechargeOrder.getPayType() == BaseQmOrder.PAY_TYPE_WXPAY) {
                    WxPayOrder wxPayOrder = wxPayOrderRepository.findByOutTradeNo(outTradeNo);
                    wxPayOrder.setRefundReason(response.getSubMsg());
                    return wxPayService.refund(wxPayOrder);
                }
            }
            publicService.parseResponse(wiredTvRechargeOrder, response.getOrderDetailInfo());
            wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);
        } catch (ApiException e) {
            wiredTvRechargeOrder.setFailReason(e.getMessage());
            wiredTvRechargeOrder.setPayResult(BaseQmOrder.STATUS_FAIL);
            wiredTvRechargeOrderRepository.save(wiredTvRechargeOrder);
            if (wiredTvRechargeOrder.getPayType() == BaseQmOrder.PAY_TYPE_ALIPAY) {
                AlipayOrder byOutTradeNo = alipayOrderRepository.findByOutTradeNo(outTradeNo);
                byOutTradeNo.setRefundReason(e.getMessage());
                return alipayService.reFund(byOutTradeNo);
            } else if (wiredTvRechargeOrder.getPayType() == BaseQmOrder.PAY_TYPE_WXPAY) {
                WxPayOrder wxPayOrder = wxPayOrderRepository.findByOutTradeNo(outTradeNo);
                wxPayOrder.setRefundReason(e.getMessage());
                return wxPayService.refund(wxPayOrder);
            }
            e.printStackTrace();
            throw new UserException("付款失败", 202);  //付款失败，走退款流程
        }
        return "error";
    }

    class Item {
        private String itemId;
        private String money;

        public Item(String itemId, String money) {
            this.itemId = itemId;
            this.money = money;
        }

        public String getItemId() {
            return itemId;
        }

        public void setItemId(String itemId) {
            this.itemId = itemId;
        }

        public String getMoney() {
            return money;
        }

        public void setMoney(String money) {
            this.money = money;
        }
    }

}
